﻿using System;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using Inovout.Gis;
using Inovout.Gis.Geometry;


namespace Inovout.ArcGis
{
    public sealed class ArcGisRow : IGisRow
    {
        #region Constructor

        private IRow arcRow;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="row"></param>
        internal ArcGisRow(IRow row)
        {
            this.arcRow = row;
        }

        #endregion

        #region Internal Property

        internal IFeature ArcFeature
        {
            get { return arcRow as IFeature; }
        }

        internal IRow ArcRow
        {
            get { return arcRow; }
        }


        #endregion


        private ArcGisTable table;
        public IGisTable Table
        {
            get
            {
                if (table == null)
                {
                    table = new ArcGisTable(arcRow.Table);
                }
                return table;
            }
        }

        internal void SetTable(ArcGisTable table)
        {
            this.table = table;
        }

        public object GeometryId
        {
            get { return arcRow.OID; }
        }

        public object this[int index]
        {
            get { return arcRow.get_Value(index); }
            set { arcRow.set_Value(index, value); }
        }
        public object this[string fieldName]
        {
            get { return this[GetFieldIndex(fieldName)]; }
            set { this[GetFieldIndex(fieldName)]=value; }
        }
        private int GetFieldIndex(string fieldName)
        {
            return arcRow.Fields.FindField(fieldName);
        }
        #region GetValueMethod
      
        public T GetValue<T>(string filedName)
        {
            return (T)this[filedName];
        }

        public bool TryGetValue(string filedName, out object value)
        {
            int fieldIndex = GetFieldIndex(filedName);
            if (fieldIndex == -1)
            {
                value = null;
                return false;
            }
            else
            {
                value = this[fieldIndex];
                return true;
            }
        }

        public bool TryGetValue<T>(string fieldName, out T value)
        {
            object resultValue;
            bool getResult = TryGetValue(fieldName, out resultValue);
            if (getResult)
            {
                value = (T)resultValue;
            }
            else
            {
                value = default(T);
            }
            return getResult;

        }
        #endregion

        public IGeometryInfo BuildGeometryInfo()
        {
            GeometryInfo geometryInfo = null;
            switch (ArcFeature.Shape.GeometryType)
            {
                case esriGeometryType.esriGeometryPolyline:
                    geometryInfo = new PolyLineInfo(this);
                    break;
                case esriGeometryType.esriGeometryPoint:
                    geometryInfo = new PointInfo(this);
                    break;
                case esriGeometryType.esriGeometryPolygon:
                    geometryInfo = new PolygonInfo(this);
                    break;
                default:
                    throw new NotImplementedException(ArcFeature.Shape.GeometryType.ToString());
            }
            geometryInfo.Layer = table.Layer;
            return GeometryFactory.CreateGeometry(geometryInfo);
        }

        #region RowMethod
    
        public void Store()
        {
            arcRow.Store();
        }
        #endregion
    }
}
